package com.gitee.melin.bee.core.hibernate5;

import com.gitee.melin.bee.core.support.Pagination;
import com.gitee.melin.bee.core.support.PaginationRequest;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.hibernate.LockOptions;
import org.hibernate.ReplicationMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.engine.jdbc.LobCreator;

/**
 * 提供了常用增删改查(CRUD)功能的DAO基础接口
 *
 * @author admin@gmail.com
 */
@SuppressWarnings("rawtypes")
public interface HibernateBaseDao<T, ID extends Serializable> {

    public LobCreator getLobCreator();

    // -------------------------------------------------------------------------
    // Convenience methods for loading individual objects
    // -------------------------------------------------------------------------
    public T get(ID id);

    public T get(final ID id, final LockOptions lockOption);

    public T load(ID id);

    public T load(final ID id, final LockOptions lockOption);

    public List<T> loadAll(Order... orders);

    public void load(final T entity, final ID id);

    public void refresh(final T entity);

    public void refresh(final T entity, final LockOptions lockOption);

    public boolean contains(final T entity);

    public void evict(final T entity);

    public void initialize(T proxy);

    /** Get the identifier of entity */
    public Serializable getIdentifierObject(T entity);

    // -------------------------------------------------------------------------
    // Convenience methods for storing individual objects
    // -------------------------------------------------------------------------

    public void lock(final T entity, final LockOptions lockOption);

    public ID save(final T entity);

    public void update(T entity);

    public void update(final T entity, final LockOptions lockOption);

    public void saveOrUpdate(final T entity);

    public void replicate(final T entity, final ReplicationMode replicationMode);

    public void persist(final T entity);

    public T merge(final T entity);

    public void delete(T entity);

    public T delete(ID id);

    public void delete(final T entity, final LockOptions lockOption);

    public void deleteAll(final Collection<T> entities);

    public Integer deleteOrUpdateByHQL(final String hql, final String paramName, final Object value);

    public Integer deleteOrUpdateByHQL(final String hql, final String[] paramNames, final Object... values);

    public void flush();

    public void clear();

    // -------------------------------------------------------------------------
    // Convenience finder methods for HQL strings
    // -------------------------------------------------------------------------
    public List findByHQL(final String queryString, final Object... values);

    public List findByHQLNamedParam(String queryString, String paramName, Object value);

    public List findByHQLNamedParam(final String queryString, final String[] paramNames, final Object[] values);

    public List findByHQLValueBean(final String queryString, final Object valueBean);

    public Pagination<T> findPageByHQL(final String rowSql, final String countSql, final int offset, final int limit);

    public Pagination<T> findPageByHQL(
            final String rowSql,
            final String countSql,
            final int offset,
            final int limit,
            final String propertyName,
            final Object value);

    public Pagination<T> findPageByHQL(
            final String rowSql,
            final String countSql,
            final int offset,
            final int limit,
            final String[] propertyNames,
            final Object[] values);

    // -------------------------------------------------------------------------
    // Convenience finder methods for dynamic detached criteria
    // -------------------------------------------------------------------------

    public List<T> findByNamedParam(String propertyName, Object value);

    public List<T> findByNamedParam(Projection projection, String propertyName, Object value);

    public T queryByNamedParam(String propertyName, Object value);

    public List<T> findByNamedParam(String joinEntity, String propertyName, Object value);

    public List<T> findByNamedParamAndOrder(String propertyName, Object value, Order... orders);

    public List<T> findByNamedParamAndOrder(Projection projection, String propertyName, Object value, Order order);

    public List<T> findByNamedParamAndOrder(String joinEntity, String propertyName, Object value, Order order);

    public List<T> findByNamedParam(String[] propertyNames, Object[] values);

    public List<T> findByNamedParam(Projection projection, String[] propertyNames, Object[] values);

    public T queryByNamedParam(String[] propertyNames, Object[] values);

    public List<T> findByNamedParamAndOrder(String[] propertyNames, Object[] values, Order... orders);

    public List<T> findByNamedParamAndOrder(
            Projection projection, String[] propertyNames, Object[] values, Order... orders);

    public List<T> findByNamedParamAndOrder(
            String[] joinEntitys, String[] propertyNames, Object[] values, Order... orders);

    public List<T> findByNamedParamAndOrder(
            Projection projection, String[] joinEntitys, String[] propertyNames, Object[] values, Order... orders);

    public Pagination<T> findPageByNamedParam(
            String joinEntity, String propertyName, Object value, final int offset, final int limit);

    public Pagination<T> findPageByNamedParam(String propertyName, Object value, final int offset, final int limit);

    public Pagination<T> findPageByNamedParam(
            Projection projection, String propertyName, Object value, final int offset, final int limit);

    public Pagination<T> findPageByNamedParamAndOrder(
            String propertyName, Object value, Order order, final int offset, final int limit);

    public Pagination<T> findPageByNamedParamAndOrder(
            Projection projection, String propertyName, Object value, Order order, final int offset, final int limit);

    public Pagination<T> findPageByNamedParam(
            String[] propertyNames, Object[] values, final int offset, final int limit);

    public Pagination<T> findPageByNamedParam(
            Projection projection, String[] propertyNames, Object[] values, final int offset, final int limit);

    public Pagination<T> findPageByNamedParamAndOrder(
            Projection projection,
            String[] propertyNames,
            Object[] values,
            Order[] orders,
            final int offset,
            final int limit);

    public Pagination<T> findPageByNamedParamAndOrder(
            String[] propertyNames, Object[] values, Order[] orders, final int offset, final int limit);

    public Pagination<T> findPageByNamedParamAndOrder(
            String[] joinEntitys,
            String[] propertyNames,
            Object[] values,
            final Order[] orders,
            final int offset,
            final int limit);

    public Pagination<T> findPageByNamedParamAndOrder(
            Projection projection,
            String[] joinEntitys,
            String[] propertyNames,
            Object[] values,
            final Order[] orders,
            final int offset,
            final int limit);

    public Pagination<T> findPage(PaginationRequest<T> paginationRequest);

    /**
     * Execute a query based on a dynamically created Hibernate criteria object. use parameters to
     * build DetachedCriteria
     *
     * @param propertyNames the names of the parameters
     * @param values the values of the parameters, values can be Criterion instance
     * @param offset the first result to retrieve, numbered from <tt>0</tt>
     * @param limit the maximum number of results
     * @return a {@link Pagination} contain query records and the total number of records
     */
    public List<T> findByNamedParam(String[] propertyNames, Object[] values, final int offset, final int limit);

    /**
     * Execute a query based on a dynamically created Hibernate criteria object. use parameters to
     * build DetachedCriteria
     *
     * @param propertyNames the names of the parameters
     * @param values the values of the parameters, values can be Criterion instance
     * @param orders {@link org.hibernate.criterion.Order} order instances
     * @param offset the first result to retrieve, numbered from <tt>0</tt>
     * @param limit the maximum number of results
     * @return a {@link Pagination} contain query records and the total number of records
     */
    public List<T> findByNamedParamAndOrder(
            String[] propertyNames, Object[] values, Order[] orders, final int offset, final int limit);

    // -------------------------------------------------------------------------
    // Convenience finder methods for named queries
    // -------------------------------------------------------------------------

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#findByNamedQuery(String, Object...)
     * @see org.springframework.orm.hibernate5.HibernateOperations#findByNamedQuery(String,
     *     Object...)
     */
    public List findByNamedQuery(final String queryName, final Object... values);

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#findByNamedParam(String, String,
     *     Object)
     * @see org.springframework.orm.hibernate5.HibernateOperations#findByNamedParam(String, String,
     *     Object)
     */
    public List findByNamedQueryAndNamedParam(String queryName, String paramName, Object value);

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#findByNamedParam(String, String[],
     *     Object[])
     * @see org.springframework.orm.hibernate5.HibernateOperations#findByNamedParam(String,
     *     String[], Object[])
     */
    public List findByNamedQueryAndNamedParam(final String queryName, final String[] paramNames, final Object[] values);

    /**
     * @see
     *     org.springframework.orm.hibernate5.HibernateTemplate#findByNamedQueryAndValueBean(String,
     *     Object)
     * @see
     *     org.springframework.orm.hibernate5.HibernateOperations#findByNamedQueryAndValueBean(String,
     *     Object)
     */
    public List findByNamedQueryAndValueBean(final String queryName, final Object valueBean);

    // -------------------------------------------------------------------------
    // Convenience finder methods for detached criteria
    // -------------------------------------------------------------------------

    public List findListByCriteria(DetachedCriteria criteria);

    public List findListByCriteria(Projection projection, DetachedCriteria criteria);

    public <R> R findByCriteria(DetachedCriteria criteria);

    /**
     * Execute a query based on a given Hibernate criteria object.
     *
     * @param criteria the detached Hibernate criteria object. <b>Note: Do not reuse criteria
     *     objects! They need to recreated per execution, due to the suboptimal design of
     *     Hibernate's criteria facility.</b>
     * @return a {@link Long} the total number of query results
     */
    public Long findCountByCriteria(final DetachedCriteria criteria);

    /**
     * Execute a page query based on a given Hibernate criteria object.
     *
     * @param criteria the detached Hibernate criteria object. <b>Note: Do not reuse criteria
     *     objects! They need to recreated per execution, due to the suboptimal design of
     *     Hibernate's criteria facility.</b>
     * @param offset the first result to retrieve, numbered from <tt>0</tt>
     * @param limit the maximum number of results
     * @return a {@link Pagination} contain query records and the total number of records
     */
    public Pagination<T> findPageByCriteria(final DetachedCriteria criteria, final int offset, final int limit);

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#findByExample(Object)
     * @see org.springframework.orm.hibernate5.HibernateOperations#findByExample(Object)
     */
    public List<T> findByExample(T exampleEntity);

    /**
     * Execute a page query based on a given Hibernate criteria object.
     *
     * @param offset the first result to retrieve, numbered from <tt>0</tt>
     * @param limit the maximum number of results
     * @return a {@link Pagination} contain query records and the total number of records
     */
    public Pagination<T> findPageByExample(final int offset, final int limit);

    /**
     * Execute a page query based on a given Hibernate criteria object.
     *
     * @param orders
     * @param offset the first result to retrieve, numbered from <tt>0</tt>
     * @param limit the maximum number of results
     * @return a {@link Pagination} contain query records and the total number of records
     */
    public Pagination<T> findPageAndOrderByExample(final Order[] orders, final int offset, final int limit);

    /**
     * @param propertyNames
     * @param values
     */
    public Long findCountByNamedParam(String[] propertyNames, Object[] values);

    /**
     * @param propertyName
     * @param value
     */
    public Long findCountByNamedParam(String propertyName, Object value);

    public Long findCount();

    // -------------------------------------------------------------------------
    // Convenience query methods for iteration and bulk updates/deletes
    // -------------------------------------------------------------------------

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#iterate(String, Object...)
     * @see org.springframework.orm.hibernate5.HibernateOperations#iterate(String, Object...)
     */
    public Iterator iterate(final String queryString, final Object... values);

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#closeIterator(Iterator)
     * @see org.springframework.orm.hibernate5.HibernateOperations#closeIterator(Iterator)
     */
    public void closeIterator(Iterator it);

    /**
     * @see org.springframework.orm.hibernate5.HibernateTemplate#bulkUpdate(String, Object...)
     * @see org.springframework.orm.hibernate5.HibernateOperations#bulkUpdate(String, Object...)
     */
    public int bulkUpdate(final String queryString, final Object... values);

    /**
     * @param joinEntitys
     * @param propertyNames
     * @param values
     */
    public DetachedCriteria createDetachedCriteria(String[] joinEntitys, String[] propertyNames, Object[] values);

    /**
     * @param joinEntitys
     * @param propertyNames
     * @param values
     */
    public DetachedCriteria createDetachedCriteria(
            List<String> joinEntitys, List<String> propertyNames, List<Object> values);
}
